package org.jili.novoland.base;

import java.util.Vector;

import org.jili.novoland.game.BattleMap;
import org.jili.novoland.game.Role;
import org.jili.novoland.util.Cfg;

import android.graphics.Canvas;

public class LayerManager {

    public LayerManager() {
        layers = new Vector<Layer>();
        viewX = viewY = 0;
        mapW = mapH = Integer.MAX_VALUE;
        viewW = Cfg.getViewWidth();
        viewH = Cfg.getViewHeight();
    }

    public void append(Layer layer) {
        synchronized (this) {
            if (layer == null)
                throw new NullPointerException();
            layers.add(layer);
        }
    }

    public Layer getLayerAt(int i) {
        // needs not be synchronized
        return (Layer) layers.get(i);
    }

    public int getLayerSize() {
        // needs not be synchronized
        return layers.size();
    }

    public void insert(Layer layer, int i) {
        synchronized (this) {
            if (layer == null)
                throw new NullPointerException();
            layers.insertElementAt(layer, i);
        }
    }

    public void remove(Layer layer) {
        synchronized (this) {
            if (layer == null)
                throw new NullPointerException();
            layers.remove(layer);
        }
    }

    public void setViewWindow(int x, int y) {
        synchronized (this) {
            viewX = x;
            viewY = y;
        }
    }

    public void drag(int dx, int dy) {
        if (viewX > 0)
            viewX = 0;
        else if (viewX < viewW - mapW)
            viewX = viewW - mapW;
        else
            viewX += dx;

        if (viewY > 0)
            viewY = 0;
        else if (viewY < viewH - mapH)
            viewY = viewH - mapH;
        else
            viewY += dy;
    }

    public void paint(Canvas c) {
        // synchronized (this) {
        if (c == null)
            throw new NullPointerException();

        // Rect clipRect = g.getClipBounds();
        // int clipX = clipRect.left;
        // int clipY = clipRect.top;
        // int clipW = clipRect.width();
        // int clipH = clipRect.height();
        // g.translate(-viewX, -viewY);
        // g.clipRect(viewX, viewY, viewW, viewH);
        for (int i = getLayerSize(); --i >= 0;) {
            Layer comp = getLayerAt(i);
            if (comp.isVisible()) {
                Actor actor = (Actor) comp;
                actor.tick();
                comp.paint(viewX, viewY, c);
            }
        }
        // g.translate(+viewX, +viewY);
        // g.clipRect(0, 0, g.getWidth(), g.getHeight(), Op.UNION);
        // g.clipRect(clipX, clipY, clipW, clipH);
        // }
    }

    public Role getCharaterByXY(int x, int y) {
        int col = getColByX(x);
        int row = getRowByY(y);
        for (int i = 0; i < roleList.size(); i++) {
            Role role = roleList.get(i);
            if (role.getCol() == col && role.getRow() == row)
                return role;
        }
        return null;

    }

    public int getColByX(int x) {
        return (x - getViewX()) / battleFieldMap.getTileWidth();

    }

    public int getRowByY(int y) {
        return (y - getViewY()) / battleFieldMap.getTileHeight();

    }

    private Vector<Layer> layers;
    private int viewX, viewY, viewW, viewH, mapW, mapH;
    private BattleMap battleFieldMap;
    private Vector<Role> roleList = new Vector<Role>();
    private Menu menu;

    public void setBattleFieldMap(BattleMap battleFieldMap) {
        this.battleFieldMap = battleFieldMap;
        mapW = battleFieldMap.getWidth();
        mapH = battleFieldMap.getHeight();
        append(battleFieldMap);
    }

    public void appendRole(Role role) {
        this.roleList.add(role);
        append(role);
    }

    public void setMenu(Menu menu) {
        this.menu = menu;
        append(menu);
    }

    public int getViewX() {
        return viewX;
    }

    public int getViewY() {
        return viewY;
    }

    public Menu getMenu() {
        return menu;
    }

    public BattleMap getBattleFieldMap() {
        return battleFieldMap;
    }
}
